﻿using MyX.Bus;
using MyX.Core;
using MyX.Message;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyX.Store
{
    internal class XEntitySaveObserver : XIEntityObserver
    {
        public void EventHappend(XEvent e)
        {
            XClient.EventRepository.Save(e);
        }
    }

    internal class XEntitySendObserver : XIEntityObserver
    {
        public void EventHappend(XEvent e)
        {
            XClient.EventBus.Send(e);
        }
    }

    internal class XMemoryRepository : XIEventRepository, XICommandRepository
    {
        public IList<XEvent> FindForEntityID(Guid id)
        {
            var entityEvents = new List<XEvent>();            

            _eventContainer.ForEach(x => entityEvents.AddRange((from p in x where p.XSenderID == id select p).ToList()));

            return entityEvents.OrderBy(x => x.Version).ToList();
        }

        public XEvent Find(Guid id)
        {
            throw new NotImplementedException();
        }

        XCommand XICommandRepository.Find(Guid id)
        {
            var entityCommand = (from p in _commands where p.ID == id select p).SingleOrDefault();
            return entityCommand;
        }

        public void Save(XCommand c)
        {
            _commands.Add(c);
        }

        public void Save(XEvent e)
        {           
            //在没有找到好的随机值生成前，先在上面使用一个并发集合，考虑重写hashcode值
            //另外，在多次测试中，多个集合与一个集合写入速度仍然一样，不清楚是线程池已满，还是随机值太过于固定，导致同一时间仍然大量写入同一集合

            //var dbIndex = e.Version % 5;

            var dbIndex = Math.Abs(e.ID.GetHashCode()) % 5;

            var events = _eventContainer[(int)dbIndex];
            events.Add(e);
        }

        private IEnumerable<XEvent> FindDB(int index, Guid id)
        {
            var entityEvents = (from p in _eventContainer[index] where p.ID == id select p);
            return entityEvents;
        }



        static XMemoryRepository()
        {
            _eventContainer = new List<ConcurrentBag<XEvent>>();

            _commands = new ConcurrentBag<XCommand>();

            _eventContainer.Add(new ConcurrentBag<XEvent>());
            _eventContainer.Add(new ConcurrentBag<XEvent>());
            _eventContainer.Add(new ConcurrentBag<XEvent>());
            _eventContainer.Add(new ConcurrentBag<XEvent>());
            _eventContainer.Add(new ConcurrentBag<XEvent>());
        }

        private static List<ConcurrentBag<XEvent>> _eventContainer;


        private static ConcurrentBag<XEvent> _events = new ConcurrentBag<XEvent>();

        private static ConcurrentBag<XCommand> _commands;
    }
}
